﻿#region Copyright information
// 
// Copyright © 2005-2013 Yongkee Cho. All rights reserved.
// 
// This code is a part of the Biological Object Library and governed under the terms of the
// GNU Lesser General  Public License (LGPL) version 2.1 which accompanies this distribution.
// For more information on the LGPL, please visit http://bol.codeplex.com/license.
// 
// - Filename: Genotype.cs
// - Author: Yongkee Cho
// - Email: yongkeecho@gmail.com
// - Date Created: 2013-01-25 3:25 PM
// - Last Modified: 2013-01-25 3:59 PM
// 
#endregion
using System;
using System.Runtime.Serialization;

namespace BOL.Models
{
    [DataContract(Namespace = "")]
    public struct Genotype<TValue> : ICloneable, INamed, IComparable, IComparable<Genotype<TValue>>, IEquatable<Genotype<TValue>>
        where TValue : IComparable
    {
        #region Public properties

        public TValue Value { get; private set; }

        public bool IsWildType { get; private set; }

        /// <summary>Gets or sets the name.</summary>
        public string Name { get; set; }

        #endregion

        #region Constructors

        public Genotype(string name, TValue value, bool isWildType = true)
            : this()
        {
            Name = name;
            Value = value;
            IsWildType = isWildType;
        }

        #endregion

        #region ICloneable implementation

        public Genotype<TValue> Clone()
        {
            return new Genotype<TValue>(Name, Value, IsWildType);
        }

        object ICloneable.Clone()
        {
            return Clone();
        }

        #endregion

        #region IComparable, IComparable<Genotype<TValue>>, IEquatable<Genotype<TValue>> implementation

        public int CompareTo(object other)
        {
            if (other == null)
                throw new ArgumentNullException();

            if (!(other is Genotype<TValue>))
                throw new InvalidCastException("The 'other' argument is not a Genotype<TValue>T object.");

            return CompareTo((Genotype<TValue>)other);
        }

        public int CompareTo(Genotype<TValue> other)
        {
            if (!Name.Equals(other.Name))
                throw new ArgumentException("Bad comparison.");

            return Value.CompareTo(other.Value);
        }

        public bool Equals(Genotype<TValue> other)
        {
            return Name.Equals(other.Name) && Value.Equals(other.Value);
        }

        #endregion

        #region Object overriden

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override bool Equals(object other)
        {
            if (other == null)
                throw new ArgumentNullException();

            if (!(other is Genotype<TValue>))
                throw new InvalidCastException("The 'other' argument is not a Genotype<TValue> object.");
            
            return Equals((Genotype<TValue>)other);
        }

        public override string ToString()
        {
            return IsWildType ? String.Format("{0} = {1} (wt)", Name, Value) : String.Format("{0} = {1}", Name, Value);
        }

        #endregion
    }
}
